package org.particlethink.utils

import com.sun.org.apache.bcel.internal.generic.RET
import java.util.*

public fun <K, T> map(arrays: List<T>, func: (T) -> K): Map<K, T> {
    val res: HashMap<K, T> = HashMap()
    for (item in arrays) {
        res[func(item)] = item
    }
    return res
}

public fun <K, T> mapList(arrays: List<T>, func: (T) -> K): Map<K, List<T>> {
    val res: HashMap<K, ArrayList<T>> = HashMap()

    arrays.forEach { item ->
        val list = res.getOrDefault(func(item), ArrayList())
        list.add(item)
        res[func(item)] = list
    }
    return res
}

public fun <U, T> reduce(arrays: List<T>, result: U, func: (U, T) -> U): U {
    var temp: U = result
    arrays.forEach { item ->
        temp = func(temp, item)
    }
    return temp
}

//public fun <U, T> reduce(arrays: List<T>, result: Result<U>, func: (U, T) -> U): U {
//    arrays.forEach { item ->
//        result.data = func(result.data, item)
//    }
//    return result.data
//}

public fun <K, V, T> mapKV(arrays: List<T>, func: (T) -> Pair<K, V>): Map<K, V> {
    val res: HashMap<K, V> = HashMap()
    arrays.forEach { item ->
        val (k, v) = func(item)
        res[k] = v
    }
    return res
}


public fun <K, V, T> filterMapKV(arrays: List<T>, func: (T) -> Triple<Boolean, K, V>): Map<K, V> {
    val res: HashMap<K, V> = HashMap()
    arrays.forEach inside@{ item ->
        val (b, k, v) = func(item)
        if (b) {
            return@inside
        }
        res[k] = v
    }
    return res
}

public fun <K, V, T> mapKVList(arrays: List<T>, func: (T) -> Pair<K, V>): Map<K, List<V>> {
    val res: HashMap<K, ArrayList<V>> = HashMap()

    arrays.forEach { item ->
        val (k, v) = func(item)
        res.getOrDefault(k, ArrayList()).add(v)
    }

    return res
}

public fun <T, U : Comparable<U>> max(arrays: List<T>?, func: (T) -> U): Optional<T & Any> {
    var tu: U? = null
    var max: T? = null
    if (arrays.isNullOrEmpty()) {
        return Optional.empty()
    }

    arrays.forEach { item ->
        if (tu == null || tu!! < func(item)) {
            tu = func(item)
            max = item
        }
    }

    return Optional.ofNullable(max)
}

public fun <T, U : Comparable<U>> min(arrays: List<T>?, func: (T) -> U): Optional<T & Any> {
    var tu: U? = null
    var min: T? = null

    if (arrays.isNullOrEmpty()) {
        return Optional.empty<T>()
    }

    arrays.forEach { item ->
        if (tu == null || tu!! > func(item)) {
            tu = func(item)
            min = item
        }
    }
    return Optional.ofNullable(min)
}


